package web

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"strconv"
	"webook/internal/domain"
	"webook/internal/service"
	"webook/pkg/ginx"
)

type ArticleHandler struct {
	svc     service.IArticleService
	intrSvc service.IInterActiveService
	Biz     string
}

func NewArticleHandler(svc service.IArticleService, intrSvc service.IInterActiveService) *ArticleHandler {
	return &ArticleHandler{
		svc:     svc,
		intrSvc: intrSvc,
		Biz:     "article",
	}
}

func (h *ArticleHandler) Edit(ctx *gin.Context) {
	// 1. 接收请求
	type Req struct {
		Id      int64  `json:"id"`
		Title   string `json:"title"`
		Content string `json:"content"`
	}
	var req Req
	if err := ctx.Bind(&req); err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[int64]{
			Code: 5,
			Msg:  "系统错误",
		})
		return
	}
	// 2. 校验请求
	// 3. 业务层处理编辑流程
	// 取出登录用户id
	loginUserId := ctx.MustGet("userId").(int64)
	id, err := h.svc.Edit(ctx, domain.Article{
		Id:      req.Id,
		Title:   req.Title,
		Content: req.Content,
		Author: domain.Author{
			Id: loginUserId,
		},
	})
	if err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[int64]{
			Code: 5,
			Msg:  "编辑帖子失败!",
		})
		// TODO 记录日志
		return
	}
	// 4. 返回响应
	ctx.JSON(http.StatusOK, ginx.Result[int64]{
		Code: 0,
		Data: id,
		Msg:  "编辑帖子成功!",
	})

}

func (h *ArticleHandler) Publish(ctx *gin.Context) {
	// 1. 接收请求
	type Req struct {
		Id      int64  `json:"id"`
		Title   string `json:"title"`
		Content string `json:"content"`
	}
	var req Req
	if err := ctx.Bind(&req); err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[int64]{
			Code: 5,
			Msg:  "系统错误",
		})
		return
	}
	// 2. 校验请求
	// 3. 业务层处理发布流程
	// 取出登录用户id
	loginUserId := ctx.MustGet("userId").(int64)
	id, err := h.svc.Publish(ctx, domain.Article{
		Id:      req.Id,
		Title:   req.Title,
		Content: req.Content,
		Author: domain.Author{
			Id: loginUserId,
		},
	})
	if err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[int64]{
			Code: 5,
			Msg:  "发布帖子失败!",
		})
		// TODO 记录日志
		return
	}
	// 4. 返回响应
	ctx.JSON(http.StatusOK, ginx.Result[int64]{
		Code: 0,
		Data: id,
		Msg:  "发布帖子成功!",
	})

}

type ListReq struct {
	Offset int `json:"offset"`
	Limit  int `json:"limit"`
}

// List 查看当前写作者的全部文章（分页）
func (h *ArticleHandler) List(ctx *gin.Context, req ListReq) (ginx.Result[any], error) {
	// 调用业务层获取分页文章
	var authorId = ctx.MustGet("userId").(int64)
	articles, err := h.svc.List(ctx, authorId, req.Offset, req.Limit)
	if err != nil {
		return ginx.Result[any]{}, err
	}
	var articleVOs = make([]ArticleVO, len(articles))
	for i, article := range articles {
		articleVOs[i] = ArticleVO{
			Id:         article.Id,
			Title:      article.Title,
			Content:    article.Content,
			Abstract:   article.GenerateAbstract(),
			AuthorId:   article.Author.Id,
			AuthorName: article.Author.Name,
			Ctime:      article.Ctime,
			Utime:      article.Utime,
		}
	}
	return ginx.Result[any]{
		Code: 0,
		Data: articleVOs,
		Msg:  "OK",
	}, nil
}

// Detail 查看当前写作者的某个具体文章
func (h *ArticleHandler) Detail(ctx *gin.Context) {
	// 获取文章id
	articleId, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[any]{
			Code: 5,
			Msg:  "系统错误!",
		})
		return
	}
	// 调用业务层获取具体文章信息
	var authorId = ctx.MustGet("userId").(int64)
	article, err := h.svc.Detail(ctx, authorId, articleId)
	if err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[any]{
			Code: 5,
			Msg:  "系统错误!",
		})
		return
	}
	ctx.JSON(http.StatusOK, ginx.Result[ArticleVO]{
		Code: 0,
		Data: ArticleVO{
			Id:       article.Id,
			Title:    article.Title,
			Content:  article.Content,
			AuthorId: article.Author.Id,
			Ctime:    article.Ctime,
			Utime:    article.Utime,
		},
		Msg: "OK",
	})
}

// PubDetail 查看线上库的具体文章信息
func (h *ArticleHandler) PubDetail(ctx *gin.Context) {
	// 获取文章id
	articleId, err := strconv.ParseInt(ctx.Param("id"), 10, 64)
	if err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[any]{
			Code: 5,
			Msg:  "系统错误!",
		})
		return
	}
	// 调用业务层获取具体文章信息
	article, err := h.svc.PubDetail(ctx, articleId)
	if err != nil {
		ctx.JSON(http.StatusOK, ginx.Result[any]{
			Code: 5,
			Msg:  "系统错误!",
		})
		return
	}
	// 需要增加文章的阅读数
	go func() {
		er := h.intrSvc.IncrReadCnt(ctx, h.Biz, articleId)
		if er != nil {
			// TODO 记录日志(增加文章阅读数失败)
		}
	}()
	ctx.JSON(http.StatusOK, ginx.Result[ArticleVO]{
		Code: 0,
		Data: ArticleVO{
			Id:         article.Id,
			Title:      article.Title,
			Content:    article.Content,
			AuthorId:   article.Author.Id,
			AuthorName: article.Author.Name,
			Ctime:      article.Ctime,
			Utime:      article.Utime,
		},
		Msg: "OK",
	})
}

type LikeReq struct {
	Id   int64 `json:"id"`
	Like bool  `json:"like"`
}

// Like 给文章点赞/取消点赞
func (h *ArticleHandler) Like(ctx *gin.Context, req LikeReq) (ginx.Result[any], error) {
	// 获取文章id
	articleId := req.Id
	userId := ctx.MustGet("userId").(int64)
	var err error
	if req.Like {
		// 调用业务层给文章点赞
		err = h.intrSvc.Like(ctx, biz, articleId, userId)
	} else {
		// 调用业务层给文章取消点赞
		err = h.intrSvc.CancelLike(ctx, biz, articleId, userId)
	}
	if err != nil {
		return ginx.Result[any]{}, err
	}
	return ginx.Result[any]{
		Code: 0,
		Msg:  "OK",
	}, nil
}

func (h *ArticleHandler) RegisterRoutes(server *gin.Engine) {
	ag := server.Group("/articles")
	ag.POST("/edit", h.Edit)
	ag.POST("/publish", h.Publish)
	// 创作者接口
	ag.POST("/list", ginx.WrapperBody[ListReq](h.List))
	ag.GET("/detail/:id", h.Detail)
	// 读者接口
	ag.GET("/pub/:id", h.PubDetail)
	ag.POST("/pub/like", ginx.WrapperBody[LikeReq](h.Like))
}
